{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 代码实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 假设我们有一个简单的线性回归模型\n",
    "# y = w * x + b\n",
    "# 其中 w 和 b 是需要学习的参数\n",
    "\n",
    "# 定义超参数\n",
    "learning_rate = 0.01\n",
    "num_epochs = 100\n",
    "\n",
    "# 随机生成训练数据\n",
    "X = torch.randn(100, 1)\n",
    "y = 2 * X + 3 + torch.randn(100, 1)\n",
    "\n",
    "# 初始化参数\n",
    "w = torch.zeros(1, requires_grad=True)\n",
    "b = torch.zeros(1, requires_grad=True)\n",
    "\n",
    "# 创建 Adagrad optimizer\n",
    "optimizer = torch.optim.Adagrad([w, b], lr=learning_rate)\n",
    "\n",
    "# 记录每次迭代的 loss\n",
    "losses = []\n",
    "\n",
    "# 训练模型\n",
    "for epoch in range(num_epochs):\n",
    "  # 计算预测值\n",
    "  y_pred = w * X + b\n",
    "\n",
    "  # 计算 loss\n",
    "  loss = torch.mean((y_pred - y) ** 2)\n",
    "\n",
    "  # 记录 loss\n",
    "  losses.append(loss.item())\n",
    "\n",
    "  # 清空上一步的梯度\n",
    "  optimizer.zero_grad()\n",
    "\n",
    "  # 计算梯度\n",
    "  loss.backward()\n",
    "\n",
    "  # 更新参数\n",
    "  optimizer.step()\n",
    "\n",
    "# 可视化训练过程\n",
    "plt.plot(losses)\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
